package com.glls.order.service.impl;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.glls.common.vo.OrderVo;
import com.glls.order.feign.AccountApi;
import com.glls.order.feign.StockApi;
import com.glls.order.mapper.OrderMapper;
import com.glls.order.service.AccountService;
import com.glls.order.service.OrderService;
import com.glls.order.service.StockService;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 *
 * @author junyang
 * @version 1.0.0
 * @date 2025/2/24 10:45
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private StockService stockService;

    @Resource
    private AccountService accountService;



    //第一种   没有事务控制  出现了 数据不一致的情况
    @Override
    public int addOrderWithNoTransaction(OrderVo order) {

        //添加订单
        int result = orderMapper.addOrder(order);

        //扣减库存
        int result2 = stockService.updateStock(order);

        //扣减余额   没有事务时     账户余额扣减异常  但是 第订单  和  库存却执行了  导致数据不一致
        int result3 = accountService.updateAccount(order);

        return result3;
    }



    //第二种情况  加事务控制
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)    // 这种写法 任何异常都会回滚
    public int addOrderWithLocalTransaction(OrderVo order) throws ClassNotFoundException {
        //添加订单
        int result = orderMapper.addOrder(order);

        //扣减库存
        int result2 = stockService.updateStock(order);

        //扣减余额
        int result3 = accountService.updateAccount(order);

        //默认情况下  遇到  检查时异常 不会滚 ，如要回滚   需要指定  rollbackFor = Exception.class
        //Class.forName("java.lang.String2");

        return result3;
    }


    @Resource
    private AccountApi accountApi;

    @Resource
    private StockApi stockApi;


    //演示 分布式事务
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    @GlobalTransactional   // 全局事务开启
    public int addOrderWithDistributeTransaction(OrderVo order) {

        //添加订单
        int result = orderMapper.addOrder(order);

        //扣减库存
        int result2 = stockApi.updateStock(order);

        //扣减余额
        int result3 = accountApi.updateAccount(order);

        if(result3 != 1){
            throw new RuntimeException("余额不足");
        }

        return result3;

    }

    @Override
    public String test3(String name) {

        if(name!=null&&name.equals("stock")){
            return stockApi.testStock();
        }else if(name!=null&&name.equals("account")){
            return accountApi.testAccount();
        }else if(name!=null&&name.equals("ex")){
            int i = 5/0;
            System.out.println("ex");
        }
        return "order-service-test3";


    }

    @Override
    @SentinelResource(value = "order-service-hotkey", blockHandler = "test6BlockHandler",fallback = "test6Fallback")
    public String test6(String name, Integer age) {

        //热点key 规则  对应的参数 为空 则不会触发对应的 热点key 规则

        if(age != null && age < 18){
            throw new RuntimeException("未成年不能进入");
        }

        return "测试热点key";
    }

    @Override
    public String test7(String testName) throws BlockException {
        // try  catch 形式 定义资源
        try(Entry entry = SphU.entry("test7resourceName")){
            if (testName != null && testName.equals("stock")) {
                return stockApi.testStock();
            } else if (testName != null && testName.equals("account")) {
                return accountApi.testAccount();
            } else if (testName != null && testName.equals("ex")) {
                int i = 5 / 0;

            } else {
                return "other";
            }
        }catch(BlockException e){
            // 资源访问阻止，被限流或被降级
            // 在此处进行相应的处理操作
            log.error("资源触发规则");
            throw e;
        }

        return "other";
    }


    public String test6BlockHandler(String name, Integer age, BlockException ex) {

        //热点key 规则  对应的参数 为空 则不会触发对应的 热点key 规则

        log.info("热点key被限流了"+ ex.getMessage());

        return "热点key被限流了";
    }

    public String test6Fallback(String name, Integer age, Throwable ex) {

        //热点key 规则  对应的参数 为空 则不会触发对应的 热点key 规则

        log.info(ex.getMessage());

        return "自定义返回，给用户友好提示";
    }
}
